package com.hnichr.ump.business.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.hnichr.ump.business.Constant;
import com.hnichr.ump.common.doc.entity.GroupUser;
import com.hnichr.ump.common.doc.entity.Order;
import com.hnichr.ump.common.doc.entity.OrderLog;
import com.hnichr.ump.common.doc.service.GroupUserService;
import com.hnichr.ump.common.doc.service.OrderLogService;
import com.hnichr.ump.common.doc.service.OrderService;
import com.hnichr.ump.common.doc.service.WeChatService;
import com.hnichr.ump.common.util.GenerateUtils;
import com.hnichr.ump.common.vo.CreateOrderVo;
import com.mxpioframework.filestorage.entity.MxpioFileInfo;
import com.mxpioframework.filestorage.service.FileStorageService;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.system.service.impl.BaseServiceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

@Service
public class OrderServiceImpl extends BaseServiceImpl<Order> implements OrderService {
	@Autowired
	private GroupUserService groupUserService;
	@Autowired
	private WeChatService weChatService;
	@Autowired
	private OrderLogService orderLogService;
	@Autowired
	private FileStorageService fileStorageService;

	@Override
	@Transactional(readOnly = false)
	public void distribute(String orderNo, String groupId) {
		if (StrUtil.isBlank(orderNo) || StrUtil.isBlank(groupId)) {
			throw new RuntimeException("缺少必要参数");
		}
		Order order = getOneOrder(orderNo);

		// 获取群组下的组员
		Criteria criteria = Criteria.create();
		criteria.addCriterion("groupId", Operator.EQ, groupId);
		List<GroupUser> groupUsers = groupUserService.list(GroupUser.class, criteria);
		if (CollectionUtil.isEmpty(groupUsers)) {
			throw new RuntimeException("群组【" + groupId + "】下没有配置人员，请联系管理员配置");
		}
		// 根据组员设置设计师、校对员、后工人员
		groupUsers.forEach(item -> {
			if (StrUtil.equals(Constant.DOC_ROLE_DISIGNER, item.getUserType())) {
				// 设计师
				order.setDesignerId(item.getUserId());
				order.setDesignerName(item.getUserName());
			} else if (StrUtil.equals(Constant.DOC_ROLE_CHECKER, item.getUserType())) {
				// 校对员
				order.setCheckId(item.getUserId());
				order.setCheckName(item.getUserName());
			} else if (StrUtil.equals(Constant.DOC_ROLE_WORKER, item.getUserType())) {
				// 后工
				order.setAfterWorkId(item.getUserId());
				order.setAfterWorkName(item.getUserName());
			}
		});

		order.setStatus(Constant.DOC_STATUS_20);
		super.save(order);

		// 记录订单日志
		criteria = Criteria.create();
		criteria.addCriterion("orderId", Operator.EQ, order.getId());
		criteria.addCriterion("content", Operator.EQ, "订单已接单");
		List<OrderLog> orderLogs = orderLogService.list(OrderLog.class, criteria);
		if (CollectionUtil.isEmpty(orderLogs)) {
			// 没有接单信息才记录
			OrderLog orderLog = new OrderLog();
			orderLog.setContent("订单已接单");
			orderLog.setAppShow(Constant.STATUS_VALID);
			orderLog.setOrderId(order.getId());
			orderLogService.save(orderLog);
		}

		weChatService.push("订单已接收", order.getWxPhone());
	}

	@Override
	@Transactional(readOnly = false)
	public void upload(MultipartFile file, String orderNo, String field) {
		Order order = getOneOrder(orderNo);

		// 上传文件
		try {
			MxpioFileInfo fileInfo = fileStorageService.put(file, file.getOriginalFilename());

			// 更新相关字段
			if (StrUtil.equals(field, "previewImage")) {
				order.setPreviewImage(fileInfo.getFileNo());
			} else if (StrUtil.equals(field, "resFile")) {
				order.setResFile(fileInfo.getFileNo());
			}
			OrderLog orderLog = new OrderLog();
			final AtomicInteger version = new AtomicInteger(1);
			if (StrUtil.equals(order.getStatus(), Constant.DOC_STATUS_20)
					|| StrUtil.equals(order.getStatus(), Constant.DOC_STATUS_31)) {
				// 已接单状态和校对不通过时，设置为初稿已完成
				order.setStatus(Constant.DOC_STATUS_30);
				orderLog.setAppShow(Constant.STATUS_INVALID);
			} else if (StrUtil.equals(order.getStatus(), Constant.DOC_STATUS_33)) {
				orderLog.setAppShow(Constant.STATUS_VALID);
			}
			// 根据订单日志设置版本号
			Criteria criteria = Criteria.create();
			criteria.addCriterion("orderId", Operator.EQ, order.getId());
			List<OrderLog> orderLogs = orderLogService.list(OrderLog.class, criteria);
			orderLogs.forEach(item -> {
				if (StrUtil.isNotBlank(item.getFileNo())
						&& !StrUtil.equals(item.getAppShow(), Constant.STATUS_DELETED)) {
					version.getAndIncrement();
				}
			});

			// 记录订单日志
			orderLog.setContent("初稿V" + NumberUtil.decimalFormat("0.0", version.get()) + "已完成");
			orderLog.setOrderId(order.getId());
			orderLog.setFileNo(fileInfo.getFileNo());
			orderLogService.save(orderLog);

			// 保存订单
			super.save(order);
		} catch (Exception e) {
			throw new RuntimeException("文件上传失败，请稍后重试");
		}
	}

	@Override
	@Transactional(readOnly = false)
	public void updateStatus(String type, String orderNo, String status) {
		Order order = getOneOrder(orderNo);

		// type: designer（设计师） check（校对师） user（客户） afterwork（后工）
		OrderLog orderLog = new OrderLog();
		orderLog.setOrderId(order.getId());
		if ("check".equals(type)) {
			if ("0".equals(status)) { // 0 校对不通过，订单状态变为“校对不通过”
				status = Constant.DOC_STATUS_31;
				orderLog.setContent("校对不通过");
				orderLog.setAppShow(Constant.STATUS_INVALID);

				// 隐藏订单日志
				Criteria criteria = Criteria.create();
				criteria.addCriterion("orderId", Operator.EQ, order.getId());
				criteria.addCriterion("content", Operator.LIKE_START, "初稿V");
				List<OrderLog> logs = orderLogService.list(OrderLog.class, criteria);
				for (OrderLog log : logs) {
					log.setAppShow(Constant.STATUS_DELETED);
				}
				orderLogService.update(logs);
				orderLogService.save(orderLog);
			} else if ("1".equals(status)) { // 1 校对通过，订单状态变为“已校对”
				status = Constant.DOC_STATUS_33;
				orderLog.setContent("初稿已提交");
				orderLog.setAppShow(Constant.STATUS_VALID);

				// 将订单日志设置为小程序可见
				Criteria criteria = Criteria.create();
				criteria.addCriterion("orderId", Operator.EQ, order.getId());
				criteria.addCriterion("content", Operator.LIKE_START, "初稿V");
				criteria.addCriterion("appShow", Operator.EQ, Constant.STATUS_INVALID);
				List<OrderLog> logs = orderLogService.list(OrderLog.class, criteria);
				for (OrderLog log : logs) {
					log.setAppShow(Constant.STATUS_VALID);
				}
				orderLogService.update(logs);
				orderLogService.save(orderLog);
			} else if ("2".equals(status)) { // 2 设计完成，订单状态变为“设计完成”，或者“设计完成待制作”
				if (Constant.DOC_BIZ_TYPE_40.equals(order.getBizType())
						|| Constant.DOC_BIZ_TYPE_50.equals(order.getBizType())) {// 40排版 50线上设计 只需要设计
					status = Constant.DOC_STATUS_36; // 设计完成，订单状态变更为设计完成
					orderLog.setContent("设计完成");
					orderLog.setAppShow(Constant.STATUS_VALID);
					orderLogService.save(orderLog);
				} else if (Constant.DOC_BIZ_TYPE_10.equals(order.getBizType())
						|| Constant.DOC_BIZ_TYPE_20.equals(order.getBizType())
						|| Constant.DOC_BIZ_TYPE_30.equals(order.getBizType())) {// 10打印 20名片制作 30条幅制作 设计+实体制作
					status = Constant.DOC_STATUS_37; // 设计完成，订单状态变更为设计完成待制作
					orderLog.setContent("设计完成待制作");
					orderLog.setAppShow(Constant.STATUS_VALID);
					orderLogService.save(orderLog);
				} else {
					throw new RuntimeException("业务类型不存在");
				}
			} else if ("3".equals(status)) { // 3 订单完成，订单状态变为“订单完成”
				status = Constant.DOC_STATUS_50;
				orderLog.setContent("订单完成");
				orderLog.setAppShow(Constant.STATUS_VALID);
				orderLogService.save(orderLog);
			}
		} else if ("user".equals(type)) {
			if (Constant.DOC_STATUS_10.equals(order.getStatus()) || Constant.DOC_STATUS_20.equals(order.getStatus())
					|| Constant.DOC_STATUS_30.equals(order.getStatus())) {
				throw new RuntimeException("订单未校对");
			} else if (Constant.DOC_STATUS_31.equals(order.getStatus())) {
				throw new RuntimeException("订单校对未通过");
			} else if (Constant.DOC_STATUS_35.equals(order.getStatus())) {
				throw new RuntimeException("订单已确认");
			} else if (Constant.DOC_STATUS_36.equals(order.getStatus())) {
				throw new RuntimeException("订单设计完成，无需确认");
			} else if (Constant.DOC_STATUS_37.equals(order.getStatus())) {
				throw new RuntimeException("订单待制作，无需确认");
			} else if (Constant.DOC_STATUS_40.equals(order.getStatus())) {
				throw new RuntimeException("订单已经制作完成，无需确认");
			} else if (Constant.DOC_STATUS_50.equals(order.getStatus())) {
				throw new RuntimeException("订单已完成，无需确认");
			}
			status = Constant.DOC_STATUS_35; // 客户确认，订单状态变更为客户已确认
			orderLog.setContent("已确认");
			orderLog.setAppShow(Constant.STATUS_VALID);
			orderLogService.save(orderLog);
		} else if ("afterwork".equals(type)) {
			if ("1".equals(status)) { // 1 制作完成，订单状态变成“制作完成”
				status = Constant.DOC_STATUS_40;
				orderLog.setContent("制作完成");
				orderLog.setAppShow(Constant.STATUS_VALID);
				orderLogService.save(orderLog);
			} else if ("2".equals(status)) { // 1 订单完成，订单状态变成“订单已完成”
				status = Constant.DOC_STATUS_50;
				orderLog.setContent("订单完成");
				orderLog.setAppShow(Constant.STATUS_VALID);
				orderLogService.save(orderLog);
			}
		}

		order.setStatus(status);
		super.update(order);

		if (Constant.DOC_STATUS_33.equals(status)) { // 已校对，推送消息让客户去确认
			weChatService.push("待确认", order.getWxPhone());
		} else if (Constant.DOC_STATUS_50.equals(status)) { // 订单已完成
			weChatService.push("订单已完成", order.getWxPhone());
		}
	}

	/**
	 * 创建订单
	 * 
	 * @param createOrderVo 订单信息
	 * @return 订单号
	 */
	@Override
	@Transactional(readOnly = false)
	public String createOrder(CreateOrderVo createOrderVo) {
		Order order = new Order();
		BeanUtil.copyProperties(createOrderVo, order);
		// 生成订单号
		order.setOrderNo(GenerateUtils.getOrderNo());
		// 设置订单状态
		order.setStatus(Constant.DOC_STATUS_10);
		double prePrice = calcPrePrice(createOrderVo);
		// 计算预报价
		BigDecimal bigDecimal = new BigDecimal(prePrice);
		order.setPrePrice(bigDecimal.setScale(2, RoundingMode.HALF_UP).doubleValue());
		order.setValidFlag(Constant.STATUS_VALID);
		// 保存订单
		save(order);

		// 记录订单日志
		OrderLog orderLog = new OrderLog();
		orderLog.setContent("创建订单");
		orderLog.setAppShow(Constant.STATUS_VALID);
		orderLog.setOrderId(order.getId());
		orderLogService.save(orderLog);
		return order.getOrderNo();
	}

	/**
	 * 计算预报价
	 * 
	 * @param createOrderVo 订单信息
	 * @return 预报价
	 */
	@Override
	public double calcPrePrice(CreateOrderVo createOrderVo) {
		/**
		 * 需求的预估价算法： （1）打印预报价=颜色*尺寸*纸张类型*数量（如果是双面打印数量要*2）+装订方式*数量 （3）名片预报价=数量*35元
		 * （4）条幅=长度*5元 （5）排版：最低100元 （6）线上设计：最低100元
		 */
		if (Constant.DOC_BIZ_TYPE_10.equals(createOrderVo.getBizType())) {
			int num = createOrderVo.getNum();
			if (Constant.DOC_PRINT_TYPE_20.equals(createOrderVo.getPrintType())) {
				num = num * 2;
			}
			if (Constant.DOC_PRINT_COLOR_10.equals(createOrderVo.getPrintColor())) {
				if (Constant.DOC_PRINT_PAPER_TYPE_10.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 0.22d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 0.12d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_20.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 0.3d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 0.16d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 0.5d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 0.3d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				}
			} else if (Constant.DOC_PRINT_COLOR_20.equals(createOrderVo.getPrintColor())) {
				if (Constant.DOC_PRINT_PAPER_TYPE_10.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 1.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 0.6d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_20.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 1.5d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 0.8d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_40.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 0.5d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 0.3d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_50.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 1.8d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 1.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_60.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 2.5d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 1.5d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_70.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 2.8d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 1.8d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_80.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 3.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 2.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else if (Constant.DOC_PRINT_PAPER_TYPE_90.equals(createOrderVo.getPrintPaperType())) {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 6.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 3.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				} else {
					if (Constant.DOC_SIZE_10.equals(createOrderVo.getSize())) {
						return 2.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					} else {
						return 1.0d * num + getBindOnePrice(createOrderVo.getBindType()) * createOrderVo.getBindNum();
					}
				}
			}
		} else if (Constant.DOC_BIZ_TYPE_20.equals(createOrderVo.getBizType())) {
			return 35.0d * createOrderVo.getNum();
		} else if (Constant.DOC_BIZ_TYPE_30.equals(createOrderVo.getBizType())) {
			return 5.0d * createOrderVo.getLength();
		} else if (Constant.DOC_BIZ_TYPE_40.equals(createOrderVo.getBizType())) {
			return 100.0d;
		} else if (Constant.DOC_BIZ_TYPE_50.equals(createOrderVo.getBizType())) {
			return 100.0d;
		}
		return 99.99d;
	}

	/**
	 * 获取装订单价
	 * 
	 * @param bindType 装订类型
	 * @return
	 */
	private double getBindOnePrice(String bindType) {
		if (Constant.DOC_BIND_TYPE_10.equals(bindType)) {
			return 1.0d;
		} else if (Constant.DOC_BIND_TYPE_20.equals(bindType)) {
			return 5.0d;
		} else if (Constant.DOC_BIND_TYPE_25.equals(bindType)) {
			return 8.0d;
		} else if (Constant.DOC_BIND_TYPE_30.equals(bindType)) {
			return 8.0d;
		} else {
			return 0d;
		}
	}

	/**
	 * 获取单个订单
	 * 
	 * @param orderNo
	 * @return
	 */
	private Order getOneOrder(String orderNo) {
		Criteria criteria = Criteria.create();
		// 获取订单信息
		criteria.addCriterion("orderNo", Operator.EQ, orderNo);
		criteria.addCriterion("validFlag", Operator.EQ, Constant.STATUS_VALID);
		List<Order> orders = super.list(Order.class, criteria);
		if (CollectionUtil.isEmpty(orders)) {
			throw new RuntimeException("未找到订单号【" + orderNo + "】匹配的数据");
		}
		return CollectionUtil.getFirst(orders);
	}

}
